iT邦幫忙

2022 iThome 鐵人賽

DAY 5
0

參數

先講結論,函式中的參數越少越好,而其中輸入型參數比輸出型來的好。
我們下面就來分別說明一下。

1. 無參數

0 個參數是最理想的狀態。

不知道大家是否還有印象,在第二天的文章中,作者認為無瑕的程式碼必須具備的要素中,其中一大要素就是通過測試,而無參數的函示是最容易被測試的。因為要寫出一個測試案例,能涵蓋參數的所有可能組合並不容易。而隨著參數的增多,複雜度更是會呈幾何增長。

除了在測試上少參數更具優勢外,

參數和函式處於不同的抽象層次,而且參數強迫你去了解目前並不那麼重要的細節。

也就是說,參數的多寡會非常直接的影響到,程式碼從閱讀到理解所耗費的時間,而這也正是程式是否易於維護、增修的重大要素。

那麼我們該如何實現無參數呢?
答案是: 實體變數。

可是這裡有一個小問題,要將參數轉化為實體變數一個很重要前提,就是有個類別(class)能夠去實例化,然而對於像 JavaScript 這樣的偽 OOP 語言來說(希望我不會被打),它其實本質上是沒有類別的概念。縱然 ES6 開始已提供關鍵字 class 和 constructor,且 TypeScript 也蔚為風潮,我身邊似乎還是鮮少見到在程式碼中大量使用類別去構築程式碼的專案。當然,其中有很大的可能是我看過的專案還太少。如果有人在 JavaScript 中大量寫 class,或對此有任何想法或指教,都非常歡迎在留言中跟我分享。

基於上述原因,就我目前所能想到的方法,JavaScript 似乎無法將單一參數函式轉化為無參數,在寫測試上也就會更複雜些。
唔......我是不是自己給出了 JavaScript 寫 class 會更好的原因?
不過話說回來,單參數函式的測試案例應該也不會說到困難,若真的困難大概也不會是參數所造成的原因。

2. 單一參數

傳遞單一參數至函式裡,有兩個極為常見的理由。(1)你也許會問『與這個參數有關的問題』,例如 boolean fileExists("MyFile")。(2)你也可能『對這個參數進行某種操作』,將該參數轉換成某樣東西,然後『回傳』。

關於上述的用法應該很容易理解,就不再贅述,然而有一種單一參數函式是作者所反對的,就是旗標參數。不幸的是,這個用法其實並不少見,其模式就是傳入一個布林值參數,當參數為 true 時做某件事,而 false 時則做另一件事。
這個方法為什麼不好呢?因為它會使函式的命名變得複雜(想想我們需要讓它有個意圖明確的稱呼),而且更重要的是,旗標參數的存在本身,就等同直接告訴所有人:這個函式做了不只一件事!

3. 兩個參數

使用兩個參數的函式並不邪惡,你必然會遇到這樣的機會。雖然如此,你仍應注意,使用使用它們有所代價。如果有一些機制可以將兩個參數轉換成一個參數時,你就應該好好利用。

讓我們來簡單地將 writeField(ouputStream, name) 用不同的方法轉化為單一參數:

<!-- 1. 將 writeField 變為 OutputStream 裡的一個成員-->
class OutputStream {
    void writeField(name){
        // 略......
    }
}

<!-- 2. 將 ouputStream 變成類別裡的成員變數 -->
class Controller {
    Stream _outputStream;
    void writeField(name){
        // 略......
    }
}

<!-- 3. 分出一個新類別 FieldWriter,將 ouputStream 引到此類別的建構子中 -->
//  略

不過也有些時候,兩個參數是很恰當的,例如宣告座標位置:

Point p = new Point(0, 0);

這種狀況下,兩個參數是由有序元件組成的單一值。如果有天看到 new Point(0),我們還反而會感到困惑。

4. 三個參數

我們應該盡量避免函式會需要三個以上的參數,事實上,當我們需要如此多的參數時,很可能可以將其包於類別或陣列中。例如:

Circle makeCircle(double x, double y, double z);

可以改為

Circle makeCircle(Point center, double z);

小結

想不到今天還是走不出函式的章節,僅分享完了關於參數的部分。明天肯定會把函式剩下的部分給結束,那麼,咱們明天再見囉!


上一篇
函式(一)
下一篇
函式(三)
系列文
重新開始學程式,【無瑕的程式碼:敏捷軟體開發技巧守則】共讀30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言